集群


1. 集群的介绍

  • 简单地说,集群就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行各自服务的独立服务器。这些服务器之间可以彼此通信,协同向用户提供应用程序,系统资源和数据,并以单一系统的模式加以管理。当用户客户机请求集群系统时,集群给用户的感觉就是一个单一独立的服务器,而实际上用户请求的是一组集群服务器

  • 打开谷歌,百度的页面,看起来好简单,也许你觉得用几分钟就可以制作出相似的网页,而实际上,这个页面的背后是由成千上万台服务器集群协同工作的结果。而这么多的服务器维护和管理,以及相互协调工作也许就是同学们未来的工作职责了

  • 若要用一句话描述集群,即一堆服务器合作做同一件事,这些机器可能需要整个技术团队架构,设计和统一协调管理,这些机器可以分布在一个机房,也可以分布在全国全球各个地区的多个机房

2. 为什么要使用集群

  • 高性能

    • 一些国家重要的计算密集型应用(如天气预报,核试验模拟等),需要计算机有很强的运算处理能力。以全世界现有的技术,即使是大型机,其计算能力也是有限的,很难单独完成此任务。因为计算时间可能会相当长,也许几天,甚至几年或更久。因此,对于这类复杂的计算业务,便使用了计算机集群技术,集中几十上百台,甚至成千上万台计算机进行计算

    • 大家耳熟能详的大型网站谷歌、百度、淘宝等,都不是几台大型机可以构建的,都是上万台服务器组成的高性能集群,分布于不同的地点

  • 价格有效性

    • 通常一套系统集群架构,只需要几台或数十台服务器主机即可。与动辄价值上百万元的专用超级计算机相比便宜了很多。在达到同样性能需求的条件下,采用计算机集群架构比采用同等运算能力的大型计算机具有更高的性价比

    • 早期的淘宝,支付宝的数据库等核心系统就是使用上百万元的小型机服务器。后因使用维护成本太高以及扩展设备费用成几何级数翻倍,甚至成为扩展瓶颈,人员维护也十分困难,最终使用PC服务器集群替换之,比如,把数据库系统从小机结合Oracle数据库迁移到MySQL开源数据库结合PC服务器上来。不但成本下降了,扩展和维护也更容易了

  • 可伸缩性

    • 当服务负载,压力增长时,针对集群系统进行较简单的扩展即可满足需求,且不会降低服务质量

    • 通常情况下,硬件设备若想扩展性能,不得不增加新的CPU和存储器设备,如果加不上去了,就不得不够买更高性能的服务器,就拿我们现在的服务器来讲,可以增加的设备总是有限的。如果采用集群技术,则只需要将新的单个服务器加入现有集群架构中即可,从访问的客户角度来看,系统服务无论是连续性还是性能上都几乎没有变化,系统在不知不觉中完成了升级,加大了访问能力,轻松地实现了扩展。集群系统中的节点数目可以增长到几千乃至上万个,其伸缩性远超过单台超级计算机

  • 高可用性

    • 单一的计算机系统总会面临设备损毁的问题,如CPU,内存,主板,电源,硬盘等,只要一个部件坏掉,这个计算机系统就可能会宕机,无法正常提供服务。在集群系统中,尽管部分硬件和软件也还是会发生故障,但整个系统的服务可以是7*24小时可用的

    • 集群架构技术可以使得系统在若干硬件设备故障发生时仍可以继续工作,这样就将系统的停机时间减少到了最小。集群系统在提高系统可靠性的同时,也大大减小了系统故障带来的业务损失,目前几乎100%的互联网网站都要求7*24小时提供服务

  • 透明性

    • 多个独立计算机组成的松耦合集群系统构成一个虚拟服务器。用户或客户端程序访问集群系统时,就像访问一台高性能,高可用的服务器一样,集群中一部分服务器的上线,下线不会中断整个系统服务,这对用户也是透明的

  • 可管理性

    • 整个系统可能在物理上很大,但其实容易管理,就像管理一个单一映像系统一样。在理想状况下,软硬件模块的插入能做到即插即用

  • 可编程性

    • 在集群系统上,容易开发及修改各类应用程序

负载均衡示意图






nginx 负载均衡概述


  • Web服务器,直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台WEB服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现负载的分发。那么会大大提升系统的吞吐率、请求性能、高容灾


  • Nginx要实现负载均衡需要用到 proxy_pass 代理模块配置

  • Nginx可以配置代理多台服务器,当一台服务器宕机之后,仍能保持系统可用

  • Nginx负载均衡与Nginx代理不同地方在于: Nginx代理仅代理一台服务器,而Nginx负载均衡则是将客户端请求代理转发至一组upstream虚拟服务池

nginx 负载均衡的配置


1. 环境的准备

  • 准备3台服务器,且都安装了 nginx

    • 10.0.0.3 -> 作为 nginx 的负载均衡器,用于将请求分发给其他服务器进行处理
    • 10.0.0.5 -> 作为处理请求减轻负载的服务器
    • 10.0.0.6 -> 作为处理请求减轻负载的服务器

  • 关闭所有服务器的防火墙

  • 所有负责减轻负载的服务器,所存放的网站项目要完全一样

2. nginx 负载均衡器的配置 -> 10.0.0.3 的配置

  • 进入 nginx 的配置文件

vim /opt/nginx-1-12/conf/nginx.conf

  • nginx 负载均衡器 的 nginx.conf 的配置文件设置

http {

  ...

# 定义一个名为 flask 的负载均衡池
upstream flask {
# 池子中存放着两个处理请求减轻负载的服务器,默认轮询方式调用服务器
        server 10.0.0.5:8000;
        server 10.0.0.6:8000;
    }

# 使用server配置网站, 每个 server{} 代表一个网站 (简称虚拟主机)
    server {
# 监听端口, 默认80
        listen 80;
 # 提供服务的域名或主机名,即: 通过该域名或ip来访问当前配置的网站
        server_name 10.0.0.3;
# 控制网站访问路径
        location / {
# 将接收到的请求转交给名为flask的负载均衡池进行分发处理
proxy_pass http://flask;
# 将 proxy_params 配置文件添加到当前虚拟主机上,且这个 proxy_params 配置文件需要手动创建到 /opt/nginx-1-12/conf/ 下
            # include 参数的作用: 减少主配置文件 nginx.conf 的内容,将某部分的配置项单独写在一个配置文件中然后使用 include 参数进行导入,其效果和直接写在 nginx.conf 主配置文件下是一样的
            # include 参数如果不使用绝对路径,那么默认会在 /opt/nginx-1-12/conf/ 下寻找你所定义的配置文件
            include proxy_params;
        }
    }

...
}

  • 在 nginx 配置文件夹(即: /opt/nginx-1-12/conf/)下创建 proxy_params 配置文件

touch /opt/nginx-1-12/conf/proxy_params

  • 打开 proxy_params 配置文件

vim /opt/nginx-1-12/conf/proxy_params

  • 配置 proxy_params 配置文件

    • 存放请求头的相关参数

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;

proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;

  • 检查nginx 负载均衡器配置文件是否有语法错误

/opt/nginx-1-12/sbin/nginx -t

  • 启动 nginx 负载均衡器 或 平滑重启 nginx 负载均衡器

    • 如果没有启动 nginx,那么就启动 nginx

/opt/nginx-1-12/sbin/nginx

    • 如果已经启动了nginx,那么在修改配置文件后,就平滑重启 nginx

/opt/nginx-1-12/sbin/nginx -s reload

3. 处理请求减轻负载的服务器配置 -> 10.0.0.5 的配置

  • 方式一: 直接使用 flask 启动 web 服务

    • 注意: 在线上部署的时候,所有负责减轻负载的服务器,所存放的网站项目要完全一样,这里只是为了查看结果才做不一样的配置

    • 在 /opt 文件夹下创建一个 flask_project 文件夹用于存放 flask 项目

mkdir /opt/flask_project

    • 在 /opt/flask_project 下创建一个 my_flask.py 文件

touch /opt/flask_project/my_flask.py

    • 进入 my_flask.py 文件

vim /opt/flask_project/my_flask.py

    • 编辑 my_flask.py 文件

from flask import Flask
app=Flask(__name__)
@app.route('/')
def hello():
    return '<h1 style="color:red">i am flask....from nginx<h1>'
if __name__=="__main__":
    app.run(host='0.0.0.0',port=8000)

    • 启动 flask 

python3 /opt/flask_project/my_flask.py

  • 方式二: 使用 nginx 启动 web 服务

    • 在 /opt/nginx-1-12/html 创建一个 nginx_fzjh.html 文件

      • 创建 nginx_fzjh.html 文件

touch /opt/nginx-1-12/html/nginx_fzjh.html

      • 修改 nginx_fzjh.html 的内容

vim /opt/nginx-1-12/html/nginx_fzjh.html

# nginx_fzjh.html

<h1 style="color:red">i am flask....from nginx<h1>

    • nginx 的 nginx.conf 的配置文件设置

http {

  ...

# 使用server配置网站, 每个 server{} 代表一个网站 (简称虚拟主机)
    server {
# 监听端口, 默认80
        listen 8000;
 # 提供服务的域名或主机名,即: 通过该域名或ip来访问当前配置的网站
        server_name 10.0.0.5;
# 控制网站访问路径
        location / {
# 存放网站代码路径
            root /opt/nginx-1-12/html/;
# 服务器返回的默认页面文件, 即: 当浏览器访问 10.0.0.5 的时候就会返回一个 index.html 页面 
            index nginx_fzjh.html;  
        }
    }

...
}

    • 检查nginx配置文件是否有语法错误

/opt/nginx-1-12/sbin/nginx -t

    • 启动nginx 或 平滑重启 nginx

      • 如果没有启动 nginx,那么就启动 nginx

/opt/nginx-1-12/sbin/nginx

      • 如果已经启动了nginx,那么在修改配置文件后,就平滑重启 nginx

/opt/nginx-1-12/sbin/nginx -s reload

4. 处理请求减轻负载的服务器配置 -> 10.0.0.6 的配置

  • 方式一: 直接使用 flask 启动 web 服务

    • 注意: 在线上部署的时候,所有负责减轻负载的服务器,所存放的网站项目要完全一样,这里只是为了查看结果才做不一样的配置

    • 在 /opt 文件夹下创建一个 flask_project 文件夹用于存放 flask 项目

mkdir /opt/flask_project

    • 在 /opt/flask_project 下创建一个 my_flask.py 文件

touch /opt/flask_project/my_flask.py

    • 进入 my_flask.py 文件

vim /opt/flask_project/my_flask.py

    • 编辑 my_flask.py 文件

from flask import Flask
app=Flask(__name__)
@app.route('/')
def hello():
    return '<h1 style="color:green">i am flask....from nginx<h1>'
if __name__=="__main__":
    app.run(host='0.0.0.0',port=8000)

    • 启动 flask 

python3 /opt/flask_project/my_flask.py

  • 方式二: 使用 nginx 启动 web 服务

    • 在 /opt/nginx-1-12/html 创建一个 nginx_fzjh.html 文件

      • 创建 nginx_fzjh.html 文件

touch /opt/nginx-1-12/html/nginx_fzjh.html

      • 修改 nginx_fzjh.html 的内容

vim /opt/nginx-1-12/html/nginx_fzjh.html

# nginx_fzjh.html

<h1 style="color:green">i am flask....from nginx<h1>

    • nginx 的 nginx.conf 的配置文件设置

http {

  ...

# 使用server配置网站, 每个 server{} 代表一个网站 (简称虚拟主机)
    server {
# 监听端口, 默认80
        listen 8000;
 # 提供服务的域名或主机名,即: 通过该域名或ip来访问当前配置的网站
        server_name 10.0.0.6;
# 控制网站访问路径
        location / {
# 存放网站代码路径
            root /opt/nginx-1-12/html/;
# 服务器返回的默认页面文件, 即: 当浏览器访问 10.0.0.6 的时候就会返回一个 index.html 页面 
            index nginx_fzjh.html;  
        }
    }

...
}

    • 检查nginx配置文件是否有语法错误

/opt/nginx-1-12/sbin/nginx -t

    • 启动nginx 或 平滑重启 nginx

      • 如果没有启动 nginx,那么就启动 nginx

/opt/nginx-1-12/sbin/nginx

      • 如果已经启动了nginx,那么在修改配置文件后,就平滑重启 nginx

/opt/nginx-1-12/sbin/nginx -s reload

5. 通过浏览器访问网站

  • 轮询访问处理请求减轻负载的服务器(即: 如果有两台处理请求减轻负载的服务器,浏览器第一次发送请求,服务器A处理,浏览器第二次发送请求后,服务器B处理

  • 浏览器第一次发送请求


  • 浏览器第二次发送请求


  • 浏览器第三次发送请求


nginx 负载均衡调度算法


调度算法
说明
轮询
按时间顺序逐一分配到不同的后端服务器(默认调度方式)
weight
加权轮询, weight值越大, 分配到的访问几率越高
ip_hash
每个请求按访问IP的hash结果分配,这样来自同一IP的固定访问一个后端服务器,且不能和 weight 一起使用
url_hash
按照访问URL的hash结果来分配请求,是每个URL定向到同一个后端服务器
least_conn
最少链接数,那个机器链接数少就分发

  • weight

http {

  ...

# 定义一个名为 flask 的负载均衡池
upstream flask {
# 池子中存放着两个处理请求减轻负载的服务器,默认轮询方式调用服务器
 server 10.0.0.5:8000 weight=3;
        server 10.0.0.6:8000 weight=7;
    }

# 使用server配置网站, 每个 server{} 代表一个网站 (简称虚拟主机)
    server {
# 监听端口, 默认80
        listen 80;
 # 提供服务的域名或主机名,即: 通过该域名或ip来访问当前配置的网站
        server_name 10.0.0.5;
# 控制网站访问路径
        location / {
# 将接收到的请求转交给名为flask的负载均衡池进行分发处理
proxy_pass http://flask;
# 将 proxy_params 配置文件添加到当前虚拟主机上,且这个 proxy_params 配置文件需要手动创建到 /opt/nginx-1-12/conf/ 下
            # include 参数的作用: 减少主配置文件 nginx.conf 的内容,将某部分的配置项单独写在一个配置文件中然后使用 include 参数进行导入,其效果和直接写在 nginx.conf 主配置文件下是一样的
            # include 参数如果不使用绝对路径,那么默认会在 /opt/nginx-1-12/conf/ 下寻找你所定义的配置文件
include proxy_params;
        }
    }

...
}

  • ip_hash

    • 根据客户端ip哈希分配,不能和 weight 一起使用

http {

  ...

# 定义一个名为 flask 的负载均衡池
upstream flask {
ip_hash;
# 池子中存放着两个处理请求减轻负载的服务器,默认轮询方式调用服务器
 server 10.0.0.5:8000;
        server 10.0.0.6:8000;
    }

# 使用server配置网站, 每个 server{} 代表一个网站 (简称虚拟主机)
    server {
# 监听端口, 默认80
        listen 80;
 # 提供服务的域名或主机名,即: 通过该域名或ip来访问当前配置的网站
        server_name 10.0.0.5;
# 控制网站访问路径
        location / {
# 将接收到的请求转交给名为flask的负载均衡池进行分发处理
proxy_pass http://flask;
# 将 proxy_params 配置文件添加到当前虚拟主机上,且这个 proxy_params 配置文件需要手动创建到 /opt/nginx-1-12/conf/ 下
            # include 参数的作用: 减少主配置文件 nginx.conf 的内容,将某部分的配置项单独写在一个配置文件中然后使用 include 参数进行导入,其效果和直接写在 nginx.conf 主配置文件下是一样的
            # include 参数如果不使用绝对路径,那么默认会在 /opt/nginx-1-12/conf/ 下寻找你所定义的配置文件
include proxy_params;
        }
    }

...
}